home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2000 / MacHack 2000.toast / pc / The Hacks / MacHacksBug / Python 1.5.2c1 / Extensions / Imaging / PIL / IptcImagePlugin.py < prev    next >
Encoding:
Python Source  |  2000-06-23  |  3.8 KB  |  202 lines

  1. #
  2. # The Python Imaging Library.
  3. # $Id: IptcImagePlugin.py,v 1.1.1.2 1999/01/13 09:40:12 sjoerd Exp $
  4. #
  5. # IPTC/NAA file handling
  6. #
  7. # history:
  8. # 95-10-01 fl    Created
  9. # 98-03-09 fl    Cleaned up and added to PIL
  10. #
  11. # Copyright (c) Secret Labs AB 1997-98.
  12. # Copyright (c) Fredrik Lundh 1995.
  13. #
  14. # See the README file for information on usage and redistribution.
  15. #
  16.  
  17.  
  18. __version__ = "0.2"
  19.  
  20.  
  21. import Image, ImageFile
  22. import os, tempfile
  23.  
  24.  
  25. COMPRESSION = {
  26.     1: "raw",
  27.     5: "jpeg"
  28. }
  29.  
  30. PAD = chr(0) * 4
  31.  
  32. #
  33. # Helpers
  34.  
  35. def i16(c):
  36.     return ord(c[1]) + (ord(c[0])<<8)
  37.  
  38. def i32(c):
  39.     return ord(c[3]) + (ord(c[2])<<8) + (ord(c[1])<<16) + (ord(c[0])<<24)
  40.  
  41. def i(c):
  42.     return i32((PAD + c)[-4:])
  43.  
  44. def dump(c):
  45.     for i in c:
  46.     print "%02x" % ord(i),
  47.     print
  48.  
  49.  
  50. #
  51. # Parser
  52.  
  53. class IptcImageFile(ImageFile.ImageFile):
  54.  
  55.     format = "IPTC"
  56.     format_description = "IPTC/NAA"
  57.  
  58.     def getint(self, key):
  59.     return i(self.info[key])
  60.  
  61.     def field(self):
  62.     #
  63.     # get a IPTC field header
  64.     s = self.fp.read(5)
  65.     if not len(s):
  66.         return None, 0
  67.  
  68.     tag = ord(s[1]), ord(s[2])
  69.  
  70.     # syntax
  71.     if ord(s[0]) != 0x1C or tag[0] < 1 or tag[0] > 9:
  72.         raise SyntaxError, "invalid IPTC/NAA file"
  73.  
  74.     # field size
  75.     size = ord(s[3])
  76.     if size > 132:
  77.         raise IOError, "illegal field length in IPTC/NAA file"
  78.     elif size == 128:
  79.         size = 0
  80.     elif size > 128:
  81.         size = i(self.fp.read(size-128))
  82.     else:
  83.         size = i16(s[3:])
  84.  
  85.     return tag, size
  86.  
  87.     def _is_raw(self, offset, size):
  88.     #
  89.     # check if the file can be mapped
  90.  
  91.     # DISABLED: the following only slows things down...
  92.     return 0
  93.  
  94.     self.fp.seek(offset)
  95.     t, sz = self.field()
  96.     if sz != size[0]:
  97.         return 0
  98.     y = 1
  99.     while 1:
  100.         self.fp.seek(sz, 1)
  101.         t, s = self.field()
  102.         if t != (8, 10):
  103.         break
  104.         if s != sz:
  105.         return 0
  106.         y = y + 1
  107.     return y == size[1]
  108.  
  109.     def _open(self):
  110.  
  111.     # load descriptive fields
  112.     while 1:
  113.         offset = self.fp.tell()
  114.         tag, size = self.field()
  115.         if not tag or tag == (8,10):
  116.         break
  117.         if size:
  118.         self.info[tag] = self.fp.read(size)
  119.         else:
  120.         self.info[tag] = None
  121.         # print tag, self.info[tag]
  122.  
  123.     # mode
  124.     layers = ord(self.info[(3,60)][0])
  125.     component = ord(self.info[(3,60)][1])
  126.     if self.info.has_key(3,65):
  127.         id = ord(self.info[(3,65)][0])-1
  128.     else:
  129.         id = 0
  130.     if layers == 1 and not component:
  131.         self.mode = "L"
  132.     elif layers == 3 and component:
  133.         self.mode = "RGB"[id]
  134.     elif layers == 4 and component:
  135.         self.mode = "CMYK"[id]
  136.  
  137.     # size
  138.     self.size = self.getint((3,20)), self.getint((3,30))
  139.  
  140.     # compression
  141.     try:
  142.         compression = COMPRESSION[self.getint((3,120))]
  143.     except KeyError:
  144.         raise IOError, "Unknown IPTC image compression"
  145.  
  146.     # tile
  147.     if tag == (8,10):
  148.         if compression == "raw" and self._is_raw(offset, self.size):
  149.         self.tile = [(compression, (offset, size + 5, -1),
  150.                  (0, 0, self.size[0], self.size[1]))]
  151.         else:
  152.         self.tile = [("iptc", (compression, offset),
  153.                  (0, 0, self.size[0], self.size[1]))]
  154.  
  155.     def load(self, modify=0):
  156.  
  157.     if len(self.tile) != 1 or self.tile[0][0] != "iptc":
  158.         return ImageFile.ImageFile.load(self, modify)
  159.  
  160.     type, tile, box = self.tile[0]
  161.  
  162.     encoding, offset = tile
  163.  
  164.     self.fp.seek(offset)
  165.  
  166.     # Copy image data to temporary file
  167.     outfile = tempfile.mktemp()
  168.     o = open(outfile, "wb")
  169.     if encoding == "raw":
  170.         # To simplify access to the extracted file,
  171.         # prepend a PPM header
  172.         o.write("P5\n%d %d\n255\n" % self.size)
  173.     while 1:
  174.         type, size = self.field()
  175.         if type != (8, 10):
  176.         break
  177.         while size > 0:
  178.         s = self.fp.read(min(size, 8192))
  179.         if not s:
  180.             break
  181.         o.write(s)
  182.         size = size - len(s)
  183.     o.close()
  184.  
  185.     try:
  186.         try:
  187.         # fast
  188.         self.im = Image.core.open_ppm(outfile)
  189.         except:
  190.         # slightly slower
  191.         im = Image.open(outfile)
  192.         im.load(modify)
  193.         self.im = im.im
  194.     finally:
  195.         try: os.unlink(outfile)
  196.         except: pass
  197.  
  198.  
  199. Image.register_open("IPTC", IptcImageFile)
  200.  
  201. Image.register_extension("IPTC", ".iim")
  202.